<template>
    <div class="snake-game">
      <canvas ref="canvasRef" class="board"></canvas>
      <div class="content">得分：{{ score }}</div>
      <div class="controls">
        <button @click="startGame">开始</button>
        <button @click="pauseGame">暂停</button>
        <button @click="resumeGame">继续</button>
        <button @click="stopGame">停止</button>
      </div>
    </div>
  </template>
  
  <script setup>
  import { ref, onMounted, onBeforeUnmount } from 'vue'
  
  const canvasRef = ref(null)
  const ctx = ref(null)
  
  const box = 20
  const rows = 17
  const cols = 17
  
  const score = ref(0)
  let snake = []
  let food = {}
  let direction = 'RIGHT'
  let changingDirection = false
  let isPaused = false
  let gameInterval = null
  let gameStarted = false
  
  const drawGame = () => {
    ctx.value.fillStyle = 'lightgray'
    ctx.value.fillRect(0, 0, cols * box, rows * box)
  
    // 食物
    ctx.value.fillStyle = 'red'
    ctx.value.fillRect(food.x, food.y, box, box)
  
    // 蛇
    ctx.value.fillStyle = 'green'
    snake.forEach(segment => {
      ctx.value.fillRect(segment.x, segment.y, box, box)
      ctx.value.strokeStyle = 'black'
      ctx.value.strokeRect(segment.x, segment.y, box, box)
    })
  }
  
  const collision = (head, body) => {
    return body.some(segment => segment.x === head.x && segment.y === head.y)
  }
  
  const updateGame = () => {
    if (isPaused) return
    changingDirection = false
  
    let head = { ...snake[0] }
    if (direction === 'LEFT') head.x -= box
    if (direction === 'UP') head.y -= box
    if (direction === 'RIGHT') head.x += box
    if (direction === 'DOWN') head.y += box
  
    if (
      head.x < 0 || head.y < 0 ||
      head.x >= cols * box || head.y >= rows * box ||
      collision(head, snake)
    ) {
      clearInterval(gameInterval)
      alert('游戏结束！你的得分：' + score.value)
      return
    }
  
    if (head.x === food.x && head.y === food.y) {
      score.value += 10
      food = generateFood()
    } else {
      snake.pop()
    }
  
    snake.unshift(head)
    drawGame()
  }
  
  const generateFood = () => ({
    x: Math.floor(Math.random() * cols) * box,
    y: Math.floor(Math.random() * rows) * box,
  })
  
  const changeDirection = (e) => {
    if (changingDirection) return
    changingDirection = true
  
    const key = e.keyCode
    if (key === 37 && direction !== 'RIGHT') direction = 'LEFT'
    else if (key === 38 && direction !== 'DOWN') direction = 'UP'
    else if (key === 39 && direction !== 'LEFT') direction = 'RIGHT'
    else if (key === 40 && direction !== 'UP') direction = 'DOWN'
  }
  
  const startGame = () => {
    gameStarted = true
    isPaused = false
    score.value = 0
    direction = 'RIGHT'
    snake = [{ x: 10 * box, y: 10 * box }]
    food = generateFood()
    clearInterval(gameInterval)
    gameInterval = setInterval(updateGame, 100)
  }
  
  const pauseGame = () => {
    if (!isPaused) {
      clearInterval(gameInterval)
      isPaused = true
    }
  }
  
  const resumeGame = () => {
    if (isPaused) {
      gameInterval = setInterval(updateGame, 100)
      isPaused = false
    }
  }
  
  const stopGame = () => {
    isPaused = false
    clearInterval(gameInterval)
    score.value = 0
    snake = [{ x: 10 * box, y: 10 * box }]
    food = generateFood()
    drawGame()
  }
  
  onMounted(() => {
    const canvas = canvasRef.value
    canvas.width = cols * box
    canvas.height = rows * box
    ctx.value = canvas.getContext('2d')
    drawGame()
    window.addEventListener('keydown', changeDirection)
  })
  
  onBeforeUnmount(() => {
    clearInterval(gameInterval)
    window.removeEventListener('keydown', changeDirection)
  })
  </script>
  
  <style scoped>
  .board {
    border: 2px solid #333;
    display: block;
    margin: 10px auto;
  }
  .controls {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 10px;
  }
  button {
    padding: 5px 10px;
  }
  .content {
    margin: 10px auto;
    padding: 0 20px;
    max-width: calc(max(1600px, 51%));
    text-align: center;
}
  </style>
  